use futures::{stream, StreamExt};
use std::path::PathBuf;
use url::Url;

use crate::{
    config::ProxyConfig,
    config::RustUpConfig,
    download::{download_and_check_hash, download_file_with_sha, DownloadOptions},
    errors::FreightResult,
};

//rustup support platforms, see https://doc.rust-lang.org/beta/rustc/platform-support.html
const PLATFORMS: &[&str] = &[
    // Tier 1 with Host Tools
    "aarch64-apple-darwin",
    "aarch64-unknown-linux-gnu",
    "i686-pc-windows-gnu",
    "i686-pc-windows-msvc",
    "i686-unknown-linux-gnu",
    "x86_64-apple-darwin",
    "x86_64-pc-windows-gnu",
    "x86_64-pc-windows-msvc",
    "x86_64-unknown-linux-gnu",
    // Tier 2 with Host Tools
    "aarch64-pc-windows-msvc",
    "aarch64-unknown-linux-musl",
    "arm-unknown-linux-gnueabi",
    "arm-unknown-linux-gnueabihf",
    "armv7-unknown-linux-gnueabihf",
    "loongarch64-unknown-linux-gnu",
    // "loongarch64-unknown-linux-musl",
    "powerpc-unknown-linux-gnu",
    "powerpc64-unknown-linux-gnu",
    "powerpc64le-unknown-linux-gnu",
    // "powerpc64le-unknown-linux-musl",
    "riscv64gc-unknown-linux-gnu",
    // "riscv64gc-unknown-linux-musl",
    "x86_64-unknown-freebsd",
    "x86_64-unknown-illumos",
    "x86_64-unknown-linux-musl",
    "x86_64-unknown-netbsd",
    // Tier 2 without Host Tools
    "aarch64-linux-android",
    "arm-linux-androideabi",
    "armv7-linux-androideabi",
    "i686-apple-darwin",
    "i686-linux-android",
    "mips-unknown-linux-gnu",
    "mips64-unknown-linux-gnuabi64",
    "mips64el-unknown-linux-gnuabi64",
    "mipsel-unknown-linux-gnu",
    "powerpc64-unknown-linux-gnu",
    "s390x-unknown-linux-gnu",
    "x86_64-linux-android",
];

#[derive(Debug, Clone, Default)]
pub struct RustUpOptions {
    pub config: RustUpConfig,

    pub proxy: ProxyConfig,

    pub rustup_path: PathBuf,
}

/// entrance function
pub async fn sync_rustup_init(opts: &RustUpOptions) -> FreightResult {
    let download_url = format!("{}/rustup/release-stable.toml", opts.config.domain);
    let file = opts.rustup_path.join("release-stable.toml");
    let down_opts = &DownloadOptions {
        proxy: opts.proxy.clone(),
        url: Url::parse(&download_url).unwrap(),
        path: file,
    };

    download_and_check_hash(down_opts, None, true)
        .await
        .unwrap();

    stream::iter(PLATFORMS)
        .for_each_concurrent(None, |platform| async move {
            let rustup_path = opts.rustup_path.clone();
            let file_name = if platform.contains("windows") {
                "rustup-init.exe".to_owned()
            } else {
                "rustup-init".to_owned()
            };
            let domain = opts.config.domain.clone();
            let proxy = opts.proxy.clone();
            let download_url = format!("{}/rustup/dist/{}/{}", domain, platform, file_name);
            let folder = rustup_path.join("dist").join(platform);
            download_file_with_sha(&download_url, &folder, &file_name, &proxy)
                .await
                .unwrap();
        })
        .await;

    Ok(())
}
